﻿using System;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace LMS.DocumentConvertService
{
    public class ConvertHelper
    {
        public static void ConvetToPdf(string sourcePath, string targetPath)
        {
            if (!File.Exists(sourcePath))
            {
                throw new Exception(string.Format("文件{0}不存在", sourcePath));
            }

            if (File.Exists(targetPath))
            {
                throw new Exception(string.Format("目标文件{0}已存在", targetPath));
            }

            LogHelper.Info<Program>("开始转换:" + Path.GetFileName(sourcePath));

            var targetDirectory = Path.GetDirectoryName(targetPath);
            if (!Directory.Exists(targetDirectory))
            {
                Directory.CreateDirectory(targetDirectory);
            }

            var ext = Path.GetExtension(sourcePath).ToLower();

            if (ext == ".ppt" || ext == ".pptx")
            {
                ConvertPptToPdf(sourcePath, targetPath);
            }
            else if (ext == ".doc" || ext == ".docx")
            {
                ConvertDocumentToPdf(sourcePath, targetPath);
            }
            else if (ext == ".xls" || ext == ".xlsx")
            {
                ConvertExcelToPdf(sourcePath, targetPath);
            }
            else
            {
                LogHelper.Info<Program>("{0}不支持转换pdf", sourcePath);
                return;
            }

            if (File.Exists(targetPath))
            {
                LogHelper.Info<Program>("转换成功:" + Path.GetFileName(sourcePath));
            }
            else
            {
                LogHelper.Info<Program>("转换失败:" + Path.GetFileName(sourcePath));
            }
        }

        /// <summary>
        /// 转换ppt文件到pdf文件（不支持超时终止）
        /// </summary>
        /// <param name="sourcePath"></param>
        /// <param name="targetPath"></param>
        private static void ConvertPptToPdf(string sourcePath, string targetPath)
        {
            NetOffice.PowerPointApi.Application application = null;
            NetOffice.PowerPointApi.Presentation presentation = null;

            var cts = new CancellationTokenSource();
            var thread = new Thread(() =>
            {
                try
                {
                    application = new NetOffice.PowerPointApi.Application();
                    presentation = application.Presentations.Open(sourcePath, true, NetOffice.OfficeApi.Enums.MsoTriState.msoTrue, false);
                    presentation.SaveCopyAs(targetPath, NetOffice.PowerPointApi.Enums.PpSaveAsFileType.ppSaveAsPDF);
                }
                catch (Exception ex)
                {
                    if (ex.InnerException != null && ex.InnerException is ThreadAbortException)
                    {
                        LogHelper.Info<Program>("ConvertPptToPdf: {0}操作超时", Path.GetFileName(sourcePath));
                    }
                    else
                    {
                        LogHelper.Error<Program>(ex, "ConvertPptToPdf: {0}出现异常", Path.GetFileName(sourcePath));
                    }
                }
                finally
                {
                    if (presentation != null)
                    {
                        presentation.Close();
                        presentation = null;
                    }

                    if (application != null)
                    {
                        application.Quit();
                        application.Dispose();
                        application = null;
                    }

                    //killProccess("POWERPNT");
                }
            });

            cts.Token.Register(() =>
            {
                thread.Abort();
            });
            cts.CancelAfter(Program.MaxThreads * 1000);

            thread.Start();
            thread.Join();

            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        /// <summary>
        /// 转换word文件到pdf文件(支持超时终止)
        /// </summary>
        /// <param name="sourcePath"></param>
        /// <param name="targetPath"></param>
        private static void ConvertDocumentToPdf(string sourcePath, string targetPath)
        {
            NetOffice.WordApi.Application application = null;
            NetOffice.WordApi.Document document = null;

            var cts = new CancellationTokenSource();
            var thread = new Thread(() =>
            {
                try
                {
                    application = new NetOffice.WordApi.Application();
                    document = application.Documents.Open(sourcePath);
                    document.ExportAsFixedFormat(targetPath, NetOffice.WordApi.Enums.WdExportFormat.wdExportFormatPDF);
                }
                catch (Exception ex)
                {
                    if (ex.InnerException != null && ex.InnerException is ThreadAbortException)
                    {
                        LogHelper.Info<Program>("ConvertDocumentToPdf: {0}操作超时", Path.GetFileName(sourcePath));
                    }
                    else
                    {
                        LogHelper.Error<Program>(ex, "ConvertDocumentToPdf: {0}出现异常", Path.GetFileName(sourcePath));
                    }
                }
                finally
                {

                    if (document != null)
                    {
                        document.Close();
                        document = null;
                    }

                    if (application != null)
                    {
                        application.Quit();
                        application.Dispose();
                        application = null;
                    }

                    //killProccess("WINWORD");
                }
            });

            cts.Token.Register(() =>
            {
                thread.Abort();
            });
            cts.CancelAfter(Program.MaxThreads * 1000);

            thread.Start();
            thread.Join();


            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        private static void ConvertExcelToPdf(string sourcePath, string targetPath)
        {
            NetOffice.ExcelApi.Application application = null;
            NetOffice.ExcelApi.Workbook wookbook = null;

            var cts = new CancellationTokenSource();
            var thread = new Thread(() =>
            {
                try
                {
                    application = new NetOffice.ExcelApi.Application();
                    wookbook = application.Workbooks.Open(sourcePath);
                    wookbook.ExportAsFixedFormat(NetOffice.ExcelApi.Enums.XlFixedFormatType.xlTypePDF, targetPath);
                }
                catch (Exception ex)
                {
                    if (ex.InnerException != null && ex.InnerException is ThreadAbortException)
                    {
                        LogHelper.Info<Program>("ConvertExcelToPdf: {0}操作超时", Path.GetFileName(sourcePath));
                    }
                    else
                    {
                        LogHelper.Error<Program>(ex, "ConvertExcelToPdf: {0}出现异常", Path.GetFileName(sourcePath));
                    }
                }
                finally
                {
                    if (wookbook != null)
                    {
                        wookbook.Close();
                        wookbook = null;
                    }

                    if (application != null)
                    {
                        application.Quit();
                        application.Dispose();
                        application = null;
                    }

                    //killProccess("EXCEL");
                }
            });

            cts.Token.Register(() =>
            {
                thread.Abort();
            });
            cts.CancelAfter(Program.MaxThreads * 1000);

            thread.Start();
            thread.Join();

            GC.Collect();
            GC.WaitForPendingFinalizers();
        }


        public static void CleanProccess()
        {
            LogHelper.Info<Program>("CleanProccess Start");
            killProccess("WINWORD");
            killProccess("EXCEL");
            LogHelper.Info<Program>("CleanProccess Finish");
        }

        private static void killProccess(string appName)
        {
            // Store all running process in the system
            Process[] runingProcess = Process.GetProcesses();
            for (int i = 0; i < runingProcess.Length; i++)
            {
                // compare equivalent process by their name
                if (string.Equals(runingProcess[i].ProcessName, appName, StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        // kill  running process
                        runingProcess[i].Kill();
                        LogHelper.Info<Program>("Kill {0} [{1}]", appName, runingProcess[i].Id);
                    }
                    catch (Exception ex)
                    {
                        if (ex is System.InvalidOperationException)
                        {
                            //进程已经关闭
                        }
                        else
                        {
                            LogHelper.Error<Program>(ex, "Kill {0} [{1}] Error", appName, runingProcess[i].Id);
                        }
                    }
                }
            }
        }
    }
}